/**
 * @file ensemble.h
 * @brief Fichier d'entête du module ensemble.
 *
 * @author Delory Rachid, Keita Mamadou, Florian Bernard
 */
#ifndef H_ENSEMBLE_H
#define H_ENSEMBLE_H
/* ********************************************************************* */
/*                                                                       */
/*                       Librairies de l'ensemble                           */
/*                                                                       */
/* ********************************************************************* */

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h> 

/* ********************************************************************* */
/*                                                                       */
/*                        Définitions de types                           */
/*                                                                       */
/* ********************************************************************* */

/**
 * @struct sItem
 * @brief Structure utilisée pour la gestion des ensembles
 *
 * Cette structure est utilisée pour gérer un ensemble. Les champs de cette structure doivent être modifiés ou lus par les accesseurs et mutateurs. Ils doivent être initialisés et libérés avec les fonctions prévus à cette effet
 */
struct sItem {
  void *data; /** Information relatif à un noeud */
  char maj; /** Si l'élément courant doit être mise à jour */
  char sup; /** Si l'élément courant doit être supprimée */
  struct sItem *suivant; /** Elément suivant de l'ensemble */
};

/**
 * @typedef Item
 * @brief Redéfinit la structure sItem
 */
  typedef struct sItem Item;

/**
 * @struct sEnsemble
 * @brief Structure utilisée pour la gestion des ensembles
 *
 * Cette structure est utilisée pour gérer un ensemble. Les champs de cette structure doivent être modifiés ou lus par les accesseurs et mutateurs. Ils doivent être initialisés et libérés avec les fonctions prévus à cette effet
 */
struct sEnsemble {
  Item *debut; /** Premier élément de l'ensemble */
  Item *courant; /** Elément courant de l'ensemble */
};

/**
 * @typedef Ensemble
 * @brief Redéfinit la structure sEnsemble
 */
  typedef struct sEnsemble Ensemble;



/* ********************************************************************* */
/*                                                                       */
/*                 Fonctions relatives aux ensembles                     */
/*                                                                       */
/* ********************************************************************* */

/**
 * @fn Ensemble * creer_Ens() ;
 * @brief Crée un ensemble en mémoire (tas)
 *
 * @return Un emsemble
 */
Ensemble * creer_Ens() ;

/**
 * @fn void init_Ens(Ensemble * ensemble);
 * @brief Initialise un ensemble
 *
 * @param ensemble
 */
void init_Ens(Ensemble * ensemble) ;

/**
 * @fn void copier_Ens(Ensemble * dest, Ensemble *src, void (*detruire)(), void (*copier)());
 * @brief Copie dans dest tout les élémenent de src
 *
 * @param[in,out] dest
 * @param src
 * @param detruire est la fonction détruire correspondant au donnée de l'ensemble
 * @param copier est la fonction de recopie correspondant au donnée de l'ensemble
 */
void copier_Ens(Ensemble ** dest, Ensemble *src, void *(*creer)(), void (*detruire)(), void (*copier)());

/**
 * @fn void insert_Ens(Ensemble * ensemble, void * data) ;
 * @brief insertion d'un item après l'élément courant de l'ensemble
 *
 * @param[in,out] ensemble
 * @param data
 */
void insert_Ens(Ensemble *ensemble, void *data, void *(*creer)(), void (*copier)());

/**
 * @fn void suppSuiv_Ens(Ensemble * ensemble) ;
 * @brief supprime l'element suivant de l'element courant de l'ensemble
 *
 * @param[in,out] ensemble
 */
void suppSuiv_Ens(Ensemble * ensemble, void (*detruire)());

/**
 * @fn void suppCourant_Ens(Ensemble * ensemble) ;
 * @brief supprime l'élément courant de l'ensemble
 *
 * @param[in,out] ensemble
 */
void suppCourant_Ens(Ensemble * ensemble, void (*detruire)());

/**
 * @fn void suppPrems_Ens(Ensemble * ensemble) ;
 * @brief supprime le premier élément de l'ensemble
 *
 * @param[in,out] ensemble
 */
void suppPrems_Ens(Ensemble * ensemble, void (*detruire)()) ;

/**
 * @fn void suivant_Ens(Ensemble * ensemble) ;
 * @brief Passe à l'élément suivant 
 *
 * @param[in, out] ensemble
 */
void suivant_Ens(Ensemble * ensemble) ;

/**
 * @fn void * getData_Ens(Ensemble * ensemble) ;
 * @brief Accès aux données stockées
 *
 * @param ensemble
 * @return la donnée stockée de l'élément courant
 */
void * getData_Ens(Ensemble * ensemble) ;

/**
 * @fn void prems_Ens(Ensemble *ensemble) ;
 * @brief Accès au premier élément de la liste
 *
 * @param ensemble
 */
void prems_Ens(Ensemble * ensemble) ;

/**
 * @fn void dernier_Ens(Ensemble * ensemble) ;
 * @brief Accès au dernier élément de la liste
 *
 * @param ensemble
 */
void dernier_Ens(Ensemble * ensemble) ;

/**
 * @fn size_t taille_Ens(Ensemble * ensemble) ;
 * @brief Calcul la taille de ensemble
 *
 * @param ensemble
 * @return la taille de l'ensemble
 */
size_t getTaille_Ens(Ensemble * ensemble) ;

/**
 * @fn void libere_Ens(Ensemble * ensemble) ;
 * @brief Libere l'ensemble initialisé par initEnsemble
 *
 * @param[in,out] ensemble
 */
void libere_Ens(Ensemble * ensemble, void (*detruire)()) ;

/**
 * @fn void detruire_Ens(Ensemble * ensemble) ;
 * @brief supprime l'ensemble
 *
 * @param[in,out] ensemble
 */
void detruire_Ens(Ensemble ** ensemble, void (*detruire)());

/**
 * @fn int estDernierElement_Ens(const Ensemble *ens) ;
 * @brief Test si l'élément courant est le dernier
 *
 * @param ens l'ensemble à tester
 * @return 0 pour non et 1 pour oui
 */
int estDernierElement_Ens(const Ensemble *ens) ;

/**
 * @fn void setMaj_Ens(Ensemble *ptr, const char b);
 * @brief Set le besoin de faire une mise à jour, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setMaj_Ens(Ensemble *ptr, const char b);

/**
 * @fn char getMaj_Ens(const Ensemble *ptr);
 * @brief Retourne 0 si pas besoin de faire la mise à jour, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getMaj_Ens(const Ensemble *ptr);

/**
 * @fn void setSup_Ens(Ensemble *ptr, const char b);
 * @brief Set le besoin de le supprimer, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setSup_Ens(Ensemble *ptr, const char b);

/**
 * @fn char getSup_Ens(const Ensemble *ptr);
 * @brief Retourne 0 si pas besoin de le supprimer, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getSup_Ens(const Ensemble *ptr);

#endif
